<template>
  <div class="tree-graph-container">
    <div class="flex">
      <el-button @click="test1">test1：简单的父子嵌套</el-button>
      <el-button @click="test2">test2：子节点的原点位置-左上角</el-button>
      <el-button @click="test3">test3：移动父节点时，边的路径点将跟随移动(注意添加边的顺序)</el-button>
      <el-button @click="test4">test4：移动父节点时，边的路径点不跟随移动(注意添加边的顺序)</el-button>
    </div>

    <div class="flex flex-row">
      <!-- 1. x6 容器 -->
      <div id="x6Container" ref="containerRef"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, shallowRef } from "vue";
import { Graph } from "@antv/x6";
import { Export } from "@antv/x6-plugin-export";

let graph: Graph | null = null;

// x6 图的实例
const graphInstance = shallowRef();

const containerRef = ref();

const test1 = () => {
  const child = graph.addNode({
    x: 120,
    y: 80,
    width: 120,
    height: 60,
    zIndex: 10,
    label: "Child\n(embedded)",
    attrs: {
      body: {
        fill: "green"
      },
      label: {
        fill: "#fff"
      }
    }
  });
  const parent = graph.addNode({
    x: 80,
    y: 40,
    width: 320,
    height: 240,
    zIndex: 1,
    label: "Parent\n(try to move me)"
  });
  parent.addChild(child);
};

const test2 = () => {
  const child1 = graph.addNode({
    x: 100,
    y: 300,
    width: 120,
    height: 60,
    label: "Child\n(inside)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#3199FF"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const child2 = graph.createNode({
    x: 360,
    y: 300,
    width: 120,
    height: 60,
    label: "Child\n(outside)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#47C769"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const parent = graph.addNode({
    x: 80,
    y: 300,
    width: 240,
    height: 160,
    zIndex: 1,
    label: "Parent\n(try to move me)",
    attrs: {
      label: { refY: 130 },
      body: {
        fill: "#fffbe6"
      }
    }
  });

  parent.addChild(child1);
  parent.addChild(child2);
};

const test3 = () => {
  const source = graph.addNode({
    x: 520,
    y: 100,
    width: 80,
    height: 40,
    label: "Child\n(source)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#3199FF"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const target = graph.addNode({
    x: 780,
    y: 80,
    width: 80,
    height: 40,
    label: "Child\n(target)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#47C769"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const parent = graph.addNode({
    x: 500,
    y: 40,
    width: 360,
    height: 160,
    zIndex: 1,
    label: "Parent\n(try to move me)",
    attrs: {
      label: { refY: 140 },
      body: {
        fill: "#fffbe6"
      }
    }
  });

  parent.addChild(source);
  parent.addChild(target);

  graph.addEdge({
    source,
    target,
    vertices: [
      { x: 620, y: 60 },
      { x: 700, y: 100 }
    ]
  });
};

const test4 = () => {
  const source = graph.addNode({
    x: 520,
    y: 400,
    width: 80,
    height: 40,
    label: "Child\n(source)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#3199FF"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const target = graph.addNode({
    x: 780,
    y: 380,
    width: 80,
    height: 40,
    label: "Child\n(target)",
    zIndex: 10,
    attrs: {
      body: {
        stroke: "none",
        fill: "#47C769"
      },
      label: {
        fill: "#fff"
      }
    }
  });

  const parent = graph.addNode({
    x: 500,
    y: 340,
    width: 360,
    height: 160,
    zIndex: 1,
    label: "Parent\n(try to move me)",
    attrs: {
      label: { refY: 140 },
      body: {
        fill: "#fffbe6"
      }
    }
  });

  graph.addEdge({
    source,
    target,
    vertices: [
      { x: 620, y: 360 },
      { x: 700, y: 400 }
    ]
  });

  parent.addChild(source);
  parent.addChild(target);
};

// 1.初始化数据
const originalData = ref({
  // 节点
  nodes: [],
  // 边
  edges: []
});
// 2.初始化画布
const init = () => {
  // 初始化 x6 图背景板
  // 创建一个新的 Graph 实例
  graph = new Graph({
    // 指定 Graph 的容器元素
    container: document.getElementById("x6Container")!,

    // 自动调整 Graph 的大小以适应容器
    autoResize: true,

    // 设置背景颜色
    background: {
      color: "#fffbe6" // 设置画布背景颜色
    },
    // 网格设置
    grid: {
      visible: true, // 渲染网格背景
      size: 10, // 网格大小 10px
      type: "doubleMesh",
      args: [
        {
          color: "#eee", // 主网格线颜色
          thickness: 1 // 主网格线宽度
        },
        {
          color: "#ddd", // 次网格线颜色
          thickness: 1, // 次网格线宽度
          factor: 4 // 主次网格线间隔
        }
      ]
    },

    // 滚动设置
    scroller: {
      enabled: false, // 启用滚动
      pannable: true // 允许通过拖动来平移视图
    },

    // 是否启用缩略图（小地图）
    minimap: false, // 禁用缩略图

    // 鼠标滚轮设置
    mousewheel: {
      enabled: true, // 启用鼠标滚轮缩放
      modifiers: ["ctrl", "meta"] // 可以通过按下 Ctrl 或 Meta 键来启用缩放
    },

    // 平移设置
    panning: {
      enabled: true, // 启用平移功能
      modifiers: "space" // 需要按住 space 键才能进行拖拽平移 大空格键
    },

    // 交互设置(拖拽移动)
    interacting: {
      nodeMovable: true
    },

    // 拖拽设置
    dragging: {
      enabled: true, // 启用拖拽功能
      ghost: false // 禁用拖拽时的虚影效果
    },

    // 当源/目标是画布上的点时，需要开启 allowBlank 选项（默认已经开启）才能生效
    connecting: {
      allowBlank: false
    }
  });

  // 渲染
  graph.fromJSON(originalData.value);
  graph.zoomToFit(); // 缩放
  graph.scale(0.7); // 设置初始缩放比例，例如 0.7 表示缩小到 70%
  // graph.centerContent(); // 居中
  graph.use(new Export()); // 加载导出插件
  graphInstance.value = graph; // 保存图实例
};

onMounted(() => {
  init(); // 初始化树数据
});
</script>

<style scoped>
#x6Container {
  flex: 1;
  width: 100%;
  height: 100vh;
  position: relative;
}
</style>
